#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
监控项时间间隔分析工具
分析监控代理的实际上报时间与配置要求的对比
"""

import re
import json
from datetime import datetime
from collections import defaultdict
import sys

def parse_log_file(log_file):
    """解析日志文件，提取监控项上报时间和配置信息"""
    
    # 配置数据存储
    config_items = {}
    upload_times = defaultdict(list)
    
    try:
        with open(log_file, 'r', encoding='utf-8') as f:
            content = f.read()
    except Exception as e:
        print(f"无法读取日志文件 {log_file}: {e}")
        return None, None
    
    # 1. 解析API响应中的配置信息
    config_pattern = r'响应内容: ({.*?})'
    config_matches = re.findall(config_pattern, content, re.DOTALL)
    
    for match in config_matches:
        try:
            response_data = json.loads(match)
            if response_data.get('code') == 200 and isinstance(response_data.get('data'), list):
                print("[配置] 发现配置数据:")
                for item in response_data['data']:
                    item_id = item.get('itemId')
                    item_name = item.get('itemName')
                    item_key = item.get('itemKey')
                    update_interval = item.get('updateIntervalSeconds', 0)
                    intervals = item.get('intervals', [])
                    
                    config_items[item_id] = {
                        'name': item_name,
                        'key': item_key,
                        'updateIntervalSeconds': update_interval,
                        'intervals': intervals
                    }
                    
                    print(f"  - ID: {item_id}, Name: {item_name}, Key: {item_key}, Interval: {update_interval}s")
                    if intervals:
                        print(f"    复杂间隔配置: {len(intervals)} 个时间窗口")
                        for i, interval in enumerate(intervals):
                            print(f"      窗口{i+1}: 周{interval.get('week')} {interval.get('startTime')}-{interval.get('endTime')} 间隔{interval.get('intervalSeconds')}s")
                break
        except json.JSONDecodeError:
            continue
    
    # 2. 解析监控项上报时间
    upload_pattern = r'time="([^"]+)".*?📊.*?监控项: ([^=]+) = ([^}]*)'
    upload_matches = re.findall(upload_pattern, content)
    
    print(f"\n[上报] 发现上报记录: {len(upload_matches)} 条")
    
    for time_str, item_key, value in upload_matches:
        try:
            # 解析时间
            timestamp = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
            upload_times[item_key.strip()].append({
                'time': timestamp,
                'value': value.strip()
            })
        except ValueError as e:
            print(f"时间解析错误: {time_str}, {e}")
    
    # 3. 额外解析系统指标采集任务的执行时间
    task_pattern = r'time="([^"]+)".*?开始执行系统指标采集和上报任务'
    task_matches = re.findall(task_pattern, content)
    
    system_task_times = []
    for time_str in task_matches:
        try:
            timestamp = datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
            system_task_times.append(timestamp)
        except ValueError:
            continue
    
    print(f"[系统] 发现系统任务执行: {len(system_task_times)} 次")
    
    return config_items, upload_times, system_task_times

def analyze_intervals(config_items, upload_times, system_task_times):
    """分析实际上报间隔与配置要求的对比"""
    
    print("\n" + "="*80)
    print("[报告] 监控项上报时间分析报告")
    print("="*80)
    
    # 分析系统任务执行间隔
    if len(system_task_times) > 1:
        print("\n[系统] 系统任务执行间隔分析:")
        intervals = []
        for i in range(1, len(system_task_times)):
            interval = (system_task_times[i] - system_task_times[i-1]).total_seconds()
            intervals.append(interval)
            print(f"  第{i}次间隔: {interval:.1f}秒 (期望: 30秒)")
        
        avg_interval = sum(intervals) / len(intervals)
        print(f"  平均间隔: {avg_interval:.1f}秒")
        print(f"  配置要求: 30秒 (config.yaml中agent.interval)")
        print(f"  偏差率: {((avg_interval - 30) / 30) * 100:.2f}%")
    
    # 映射itemKey到itemId
    key_to_id = {}
    key_to_config = {}
    for item_id, config in config_items.items():
        key = config['key']
        key_to_id[key] = item_id
        key_to_config[key] = config
    
    print(f"\n[监控项] 各监控项上报情况分析:")
    print(f"{'监控项名称':<20} {'配置间隔':<10} {'实际上报次数':<12} {'分析结果':<30}")
    print("-" * 80)
    
    # 计算测试总时长
    if system_task_times:
        test_duration = (system_task_times[-1] - system_task_times[0]).total_seconds()
        print(f"测试时长: {test_duration:.1f}秒 ({test_duration/60:.2f}分钟)")
    
    for item_key, uploads in upload_times.items():
        if item_key in key_to_config:
            config = key_to_config[item_key]
            expected_interval = config['updateIntervalSeconds']
            item_name = config['name']
            intervals = config.get('intervals', [])
            
            upload_count = len(uploads)
            
            # 计算期望的上报次数
            if system_task_times and expected_interval > 0:
                expected_count = max(1, int(test_duration / expected_interval))
            else:
                expected_count = len(system_task_times)  # 备用上报模式，跟随系统任务
            
            # 分析结果
            if intervals:  # 有复杂间隔配置
                result = f"复杂间隔({len(intervals)}个时间窗口)"
            elif upload_count == len(system_task_times):
                result = "备用上报模式(30s间隔)"
            elif abs(upload_count - expected_count) <= 1:
                result = "[OK] 符合预期"
            else:
                result = f"[WARN] 偏差较大(期望{expected_count}次)"
            
            print(f"{item_name:<20} {expected_interval:<10}s {upload_count:<12} {result:<30}")
            
            # 详细时间分析
            if len(uploads) > 1:
                actual_intervals = []
                for i in range(1, len(uploads)):
                    interval = (uploads[i]['time'] - uploads[i-1]['time']).total_seconds()
                    actual_intervals.append(interval)
                
                avg_actual = sum(actual_intervals) / len(actual_intervals)
                print(f"  └─ 实际平均间隔: {avg_actual:.1f}秒")
                
                if intervals:
                    print(f"  └─ 时间窗口配置:")
                    for interval in intervals:
                        print(f"     周{interval.get('week')} {interval.get('startTime')}-{interval.get('endTime')} 间隔{interval.get('intervalSeconds')}s")
        else:
            print(f"未知监控项: {item_key} (上报{len(uploads)}次)")
    
    print("\n" + "="*80)
    
    return True

def generate_detailed_report(config_items, upload_times, system_task_times):
    """生成详细的时间分析报告"""
    
    report_content = []
    report_content.append("# 监控项时间间隔测试报告")
    report_content.append(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    report_content.append("")
    
    # 测试概要
    if system_task_times:
        start_time = system_task_times[0].strftime('%H:%M:%S')
        end_time = system_task_times[-1].strftime('%H:%M:%S')
        duration = (system_task_times[-1] - system_task_times[0]).total_seconds()
        report_content.append("## 测试概要")
        report_content.append(f"- 测试开始时间: {start_time}")
        report_content.append(f"- 测试结束时间: {end_time}")
        report_content.append(f"- 测试持续时间: {duration:.1f}秒 ({duration/60:.2f}分钟)")
        report_content.append(f"- 系统任务执行次数: {len(system_task_times)}次")
        report_content.append("")
    
    # 配置信息
    report_content.append("## 配置信息")
    report_content.append("### 从API获取的监控项配置")
    report_content.append("| 监控项ID | 名称 | ItemKey | 配置间隔(s) | 复杂间隔 |")
    report_content.append("|----------|------|---------|-------------|----------|")
    
    for item_id, config in config_items.items():
        intervals = config.get('intervals', [])
        complex_info = f"{len(intervals)}个时间窗口" if intervals else "无"
        report_content.append(f"| {item_id} | {config['name']} | {config['key']} | {config['updateIntervalSeconds']} | {complex_info} |")
    
    report_content.append("")
    
    # 实际上报分析
    report_content.append("## 实际上报分析")
    
    # 系统任务间隔分析
    if len(system_task_times) > 1:
        report_content.append("### 系统任务执行间隔")
        intervals = []
        for i in range(1, len(system_task_times)):
            interval = (system_task_times[i] - system_task_times[i-1]).total_seconds()
            intervals.append(interval)
        
        avg_interval = sum(intervals) / len(intervals)
        deviation = ((avg_interval - 30) / 30) * 100
        
        report_content.append(f"- 配置间隔: 30秒")
        report_content.append(f"- 实际平均间隔: {avg_interval:.1f}秒")
        report_content.append(f"- 偏差率: {deviation:.2f}%")
        report_content.append("")
        
        # 详细间隔列表
        report_content.append("#### 详细间隔记录")
        for i, interval in enumerate(intervals, 1):
            report_content.append(f"第{i}次间隔: {interval:.1f}秒")
        report_content.append("")
    
    # 各监控项详细分析
    report_content.append("### 各监控项详细分析")
    
    key_to_config = {}
    for item_id, config in config_items.items():
        key_to_config[config['key']] = config
    
    for item_key, uploads in upload_times.items():
        if item_key in key_to_config:
            config = key_to_config[item_key]
            report_content.append(f"#### {config['name']} ({item_key})")
            report_content.append(f"- 配置间隔: {config['updateIntervalSeconds']}秒")
            report_content.append(f"- 实际上报次数: {len(uploads)}次")
            
            if config.get('intervals'):
                report_content.append("- 复杂间隔配置:")
                for i, interval in enumerate(config['intervals'], 1):
                    report_content.append(f"  - 窗口{i}: 周{interval.get('week')} {interval.get('startTime')}-{interval.get('endTime')} 间隔{interval.get('intervalSeconds')}秒")
            
            if len(uploads) > 1:
                actual_intervals = []
                for i in range(1, len(uploads)):
                    interval = (uploads[i]['time'] - uploads[i-1]['time']).total_seconds()
                    actual_intervals.append(interval)
                
                avg_actual = sum(actual_intervals) / len(actual_intervals)
                report_content.append(f"- 实际平均间隔: {avg_actual:.1f}秒")
                
                # 上报时间列表
                report_content.append("- 上报时间记录:")
                for i, upload in enumerate(uploads, 1):
                    time_str = upload['time'].strftime('%H:%M:%S')
                    report_content.append(f"  - 第{i}次: {time_str} (值: {upload['value']})")
            
            report_content.append("")
    
    # 问题分析
    report_content.append("## 问题分析")
    report_content.append("### 发现的问题")
    report_content.append("1. **动态监控项调度器未启动**: 日志显示\"动态监控项调度器未启动，使用硬编码上报作为备用\"")
    report_content.append("2. **所有监控项都使用备用上报模式**: 实际上报间隔都是30秒，而不是配置中的个性化间隔")
    report_content.append("3. **复杂间隔配置未生效**: 主机名监控项配置了复杂时间窗口，但未按预期执行")
    report_content.append("")
    
    report_content.append("### 原因分析")
    report_content.append("1. 配置更新回调可能没有成功触发动态调度器的启动")
    report_content.append("2. 系统使用了备用上报机制，所有监控项都跟随系统任务的30秒间隔")
    report_content.append("3. 需要检查配置管理器的回调机制是否正常工作")
    report_content.append("")
    
    report_content.append("### 建议解决方案")
    report_content.append("1. 检查配置管理器的`onConfigUpdate`回调是否正确注册")
    report_content.append("2. 确认调度器的`startItemSchedulers`方法是否被正确调用")
    report_content.append("3. 添加更多调试日志，跟踪动态调度器的启动过程")
    report_content.append("4. 验证复杂间隔配置的解析和时间窗口匹配逻辑")
    
    return "\n".join(report_content)

def main():
    log_file = "monitoring_test_output.log"
    
    print("[分析] 开始分析监控项时间间隔...")
    print(f"日志文件: {log_file}")
    
    config_items, upload_times, system_task_times = parse_log_file(log_file)
    
    if not config_items:
        print("[错误] 未找到配置信息，请检查日志文件")
        return
    
    print(f"[完成] 解析完成: 配置项 {len(config_items)} 个, 上报记录 {sum(len(times) for times in upload_times.values())} 条")
    
    # 执行分析
    analyze_intervals(config_items, upload_times, system_task_times)
    
    # 生成详细报告
    report_content = generate_detailed_report(config_items, upload_times, system_task_times)
    
    report_file = "monitoring_intervals_analysis_report.md"
    try:
        with open(report_file, 'w', encoding='utf-8') as f:
            f.write(report_content)
        print(f"[报告] 详细报告已保存到: {report_file}")
    except Exception as e:
        print(f"[错误] 保存报告失败: {e}")
    
    print("\n[完成] 分析完成!")

if __name__ == "__main__":
    main()